/**
 * @created feb. 26, 2004
 * @author fsemiond
 *
 * @modified mar 1, 2007
 * @author jprieur
 * 
 */
package mygui;

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;

import communication.secondLayer.ProtocoleCsmaca;
import communication.secondLayer.SecondLayerProtocol;
import communication.thirdLayer.ThirdLayerProtocol;
import kernel.Simulator;
import kernel.SensorSimulator;
import utils.ObjectReader;
import utils.ObjectWriter;

public class MonIHM extends JFrame implements WindowListener
{
    protected static MonIHM instance;
    protected Simulator _kernel;

    public static final int WIDTH = 800;
    public static final int HEIGHT = 600;	

    private JButton _new;
    private JButton _open;
    private JButton _save;

    private JButton _preferences;

    private JButton _arrow;
    private JButton _erase;

    protected JToggleButton _mobile;
    protected JToggleButton _base;

    protected JToggleButton _network;
    protected JToggleButton _sink;

    private JButton _rectangle;
    private JButton _circle;
    private JButton _play;
    private JButton _pause;
    private JButton _stop;
    private JButton _reload;
    private JButton _snapshot;
    private JButton _faster;
    private JButton _slower;

    private JButton _generate;
    private JButton _results;

    private JButton _about;
    private JButton _leave;
    
    protected DisplayPanel _display;

    protected ObjectsTree _display_tree;
    protected JScrollPane _display_tree_scroller;
    protected MonitorPanel _monitor_panel;
    protected JScrollPane _display_scroller;
    private Rule _columnView;
    private Rule _rowView;
    protected StatusBar _status;
   
    public MonitorPanel getMonitor()
    {
	return _monitor_panel;
    }    

    public JPanel getDisplay()
    {
	return _display;
    }

    /**
     * Constructor.
     * @param simMode the structure mode of the simulation.
     */
    public MonIHM(int mode){
	instance = this;
	// Kernel initialization
	if(mode == Simulator.SENSOR){
	    _kernel = new SensorSimulator(this, mode);
	    this._kernel.setProtocol2(SecondLayerProtocol.CSMACA);
	}else{
	    _kernel = new Simulator(this, mode);
	    this._kernel.setProtocol2(SecondLayerProtocol.CSMACA);
	    this._kernel.setProtocol3(ThirdLayerProtocol.AODV);
	}
	buildGui();
    }

    public void leaveModes()
    {
	_mobile.setSelected(false);
	_base.setSelected(false);
	_network.setSelected(false);
	_sink.setSelected(false);
    }

    private void buildGui() {
	setLayout(new BorderLayout());
	setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);

	// Menu bar
	JMenuBar menubar = new JMenuBar();
	JMenu file = new JMenu("File");
	file.add(new JMenuItem(new ActionNew(this)));
	file.add(new JMenuItem(new ActionOpen(this)));
	file.add(new JMenuItem(new ActionSave(this)));
	file.addSeparator();
	file.add(new JMenuItem(new ActionExit(this)));
	menubar.add(file);
	JMenu results = new JMenu("Results");
	results.add(new JMenuItem(new ActionResultsStudio(this)));
	menubar.add(results);
	JMenu help = new JMenu("Help");
	help.add(new JMenuItem(new ActionAbout(this)));
	menubar.add(help);
	//this.setJMenuBar(menubar);

	// Toolbar
	JToolBar toolBar = new JToolBar("Toolbar");
	_new = new JButton(new ActionNew(this));_new.setText("");
	_open = new JButton(new ActionOpen(this));_open.setText("");
	_save = new JButton(new ActionSave(this));_save.setText("");
	_preferences = new JButton(new ActionPreferences(this));_preferences.setText("");
	_arrow = new JButton(new ActionArrow(this));_arrow.setText("");
	_erase = new JButton(new ActionEraseObject(this));_erase.setText("");

	_mobile = new JToggleButton(new ActionAddMobileStation(this));_mobile.setText("");
	_base = new JToggleButton(new ActionAddBaseStation(this));_base.setText("");

	_network = new JToggleButton(new ActionAddNetwork(this));_network.setText("");
	_sink = new JToggleButton(new ActionAddSink(this));_sink.setText("");

	_rectangle = new JButton(new ActionAddRectangleObstacle(this));_rectangle.setText("");
	_circle = new JButton(new ActionAddCircleObstacle(this));_circle.setText("");
	_play = new JButton(new ActionPlay(this));_play.setText("");
	_pause = new JButton(new ActionPause(this));_pause.setText("");
	_stop = new JButton(new ActionStop(this));_stop.setText("");
	_reload = new JButton(new ActionReload(this));_reload.setText("");
	_snapshot = new JButton();
	//_snapshot = new JButton(new ActionSnapshot(this));_snapshot.setText("");
	_faster = new JButton(new ActionFaster(this));_faster.setText("");
	_slower = new JButton(new ActionSlower(this));_slower.setText("");

	_generate = new JButton(new ActionGenerateResults());_generate.setText("");
	_results = new JButton(new ActionResultsStudio(this));_results.setText("");

	_about = new JButton(new ActionAbout(this));_about.setText("");
	_leave = new JButton(new ActionExit(this));_leave.setText("");

	toolBar.add(_new);
	toolBar.add(_open);
	toolBar.add(_save);
	toolBar.addSeparator();
	toolBar.add(_preferences);
	toolBar.addSeparator();
	toolBar.add(_arrow);
	toolBar.add(_erase);

	if(_kernel.getMode() == Simulator.SENSOR){
	    toolBar.add(_network);
	    toolBar.add(_sink);
	}else{
	    toolBar.add(_mobile);
	    if(_kernel.getMode() != Simulator.ADHOC)
		toolBar.add(_base);
	}

	toolBar.add(_rectangle);
	//toolBar.add(_circle);
	toolBar.addSeparator();
	toolBar.add(_play);
	toolBar.add(_pause);
	toolBar.add(_stop);
	toolBar.add(_reload);
	//toolBar.add(_snapshot);	
	//toolBar.add(_faster);
	//toolBar.add(_slower);
	toolBar.addSeparator();	
	toolBar.add(_generate);
	toolBar.add(_results);
	toolBar.addSeparator();
	toolBar.add(_about);
	toolBar.addSeparator();
	toolBar.add(_leave);

	add("North", toolBar);

	// Status
	_status = new StatusBar();
	add("South", _status);

	// Adding display panel with scrollbars and zoom button
	_display = new DisplayPanel(_kernel, this);
	if(_kernel.getMode() == Simulator.SENSOR){
	    _display_tree = new ObjectsTreeSensor(this);
	}else{
	    _display_tree = new ObjectsTree(this);
	}
	Simulator.getSimulator().addObserver(_display_tree);
	_columnView = new Rule(Rule.HORIZONTAL, _display);
	_rowView = new Rule(Rule.VERTICAL, _display);
	_display_scroller = new JScrollPane(_display);
	JButton zoom = new JButton(UIM.createImageIcon("images/zoom.png", 
						       "Magnify the display"));
	zoom.setBackground(new Color(240, 255, 240));
	zoom.setBorder(new EmptyBorder(0,0,0,0));
	zoom.addMouseListener(new MouseListener()
	    {
		public void mouseClicked(MouseEvent e)
		{
		    switch(e.getButton()){
		    case MouseEvent.BUTTON1:
			_display.setZoom(_display.getZoom() + 1);
			break;
		    case MouseEvent.BUTTON3:
			_display.setZoom(_display.getZoom() - 1);
			break;
		    }
		    _columnView.repaint();
		    _rowView.repaint();
		}
		public void mouseExited(MouseEvent e){}
		public void mouseEntered(MouseEvent e){}
		public void mousePressed(MouseEvent e){}		
		public void mouseReleased(MouseEvent e){}		
	    });
	_columnView.setPreferredWidth(Simulator.getTailleY() * _display.getZoom());
	_rowView.setPreferredHeight(Simulator.getTailleX() * _display.getZoom());
	_display_scroller.setColumnHeaderView(_columnView);
        _display_scroller.setRowHeaderView(_rowView);

	Corner a = new Corner();

	_display_scroller.setCorner(JScrollPane.UPPER_LEFT_CORNER, zoom);
	_display_scroller.setCorner(JScrollPane.LOWER_LEFT_CORNER,
                                    new Corner());
        _display_scroller.setCorner(JScrollPane.UPPER_RIGHT_CORNER,
                                    new Corner());

	_display_tree_scroller = new JScrollPane(_display_tree);

	_monitor_panel = new MonitorPanel();
	_monitor_panel.setPreferredSize(new Dimension(20,60));
	JSplitPane split2 = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
					   _display_tree_scroller,
					   _monitor_panel);
	JSplitPane split = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
					  split2,
					  _display_scroller);

	split.setOneTouchExpandable(true); 
	split2.setOneTouchExpandable(true); 
	add("Center", split);
	//add("East", informationPane);
	//add("West", _display_tree);

	updateCommandes();

	// Window
	String mode = "";
	if(_kernel.getMode() == Simulator.SENSOR){
	    mode = "sensor network";
	}else if (_kernel.getMode() == Simulator.INFRA){
	    mode = "infrastructure";
	}else if (_kernel.getMode() == Simulator.HYBRID){
	    mode = "hybrid";
	}else if (_kernel.getMode() == Simulator.ADHOC){
	    mode = "adhoc";
	}
	this.addWindowListener(this);
	setTitle("simmobil ("+mode+")");
	setSize(WIDTH, HEIGHT);
	setVisible(true);
	pack();
    }

    public void windowActivated(WindowEvent e){}
    public void windowClosed(WindowEvent e){}
    public void windowClosing(WindowEvent e)
    {
	String msg = "Do you want to quit simmobil?";
	int n = JOptionPane.showConfirmDialog(this,
					      msg,
					      "simmobil",
					      JOptionPane.YES_NO_OPTION);
	if(n == JOptionPane.YES_OPTION){
	    // TODO : handle save unsaved changes
	    System.exit(0);
	}else{
	    setVisible(true);
	}
    }
    public void windowDeactivated(WindowEvent e){}
    public void windowDeiconified(WindowEvent e){}
    public void windowIconified(WindowEvent e){}
    public void windowOpened(WindowEvent e){}


    /**
     * Accessor to the Canvas Affichage of the Application
     * @return the Canvas Affichage of the Application
     */
    public DisplayPanel getAffichage()
    {
	return _display;
    }

    /**
     * Set the text in the description
     * @param a the text you want to set in the description
     */
    public void setDescription(String a){
	_status._action.setText("a");
    }

    /**
     * Get the simulator 
     * Used only in the snapshot case 
     * @param a the text you want to set in the description
     */
    protected Simulator getSimulator(){
	return _kernel;
    }

    /**
     * Set the simulator 
     * Used only in the snapshot case 
     * @param a the text you want to set in the description
     */
    protected void setSimulator(Simulator kernel){
	_kernel = kernel;
	_display.setSimulator(kernel);
	_display_tree = null;
	//this.informationPane.setSimulator(kernel);

	if(_kernel.getMode() == Simulator.SENSOR){
	    _display_tree = new ObjectsTreeSensor(this);
	}else{
	    _display_tree = new ObjectsTree(this);
	}
	_display_tree_scroller.setViewportView(_display_tree);
	Simulator.getSimulator().addObserver(_display_tree);

	_monitor_panel.clear();

	updateCommandes();
    }

    /**
     * Repaints the commandeBar and updates the menus
     */
    public void updateCommandes()
    {	
	switch(_kernel.getState()){
	case Simulator.INIT:
	    _network.setSelected(false);
	    _new.setEnabled(true);
	    _open.setEnabled(true);
	    _save.setEnabled(true);
	    _arrow.setEnabled(true);
	    _erase.setEnabled(true);
	    _mobile.setEnabled(true);
	    _base.setEnabled(true);
	    _sink.setEnabled(true);
	    _network.setEnabled(true);
	    _rectangle.setEnabled(true);
	    _circle.setEnabled(true);
	    _play.setEnabled(true);
	    _pause.setEnabled(false);
	    _stop.setEnabled(false);
	    _reload.setEnabled(false);
	    _snapshot.setEnabled(false);
	    _faster.setEnabled(false);
	    _slower.setEnabled(false);
	    _generate.setEnabled(false);
	    _results.setEnabled(true);
	    break;
	case Simulator.PLAY:
	    _network.setSelected(false);
	    _new.setEnabled(false);
	    _open.setEnabled(false);
	    _save.setEnabled(false);
	    _arrow.setEnabled(false);
	    _erase.setEnabled(false);
	    _mobile.setEnabled(false);
	    _sink.setEnabled(false);
	    _network.setEnabled(false);
	    _base.setEnabled(false);
	    _rectangle.setEnabled(false);
	    _circle.setEnabled(false);
	    _play.setEnabled(false);
	    _pause.setEnabled(true);
	    _stop.setEnabled(true);
	    _reload.setEnabled(true);
	    _snapshot.setEnabled(false);
	    _faster.setEnabled(true);
	    _slower.setEnabled(true);
	    _generate.setEnabled(false);
	    _results.setEnabled(true);
	    break;
	case Simulator.PAUSE:
	    _network.setSelected(false);
	    _new.setEnabled(false);
	    _open.setEnabled(false);
	    _save.setEnabled(false);
	    _arrow.setEnabled(false);
	    _erase.setEnabled(false);
	    _mobile.setEnabled(false);
	    _base.setEnabled(false);
	    _sink.setEnabled(false);
	    _network.setEnabled(false);
	    _rectangle.setEnabled(false);
	    _circle.setEnabled(false);
	    _play.setEnabled(true);
	    _pause.setEnabled(false);
	    _stop.setEnabled(true);
	    _reload.setEnabled(true);
	    _snapshot.setEnabled(true);
	    _faster.setEnabled(true);
	    _slower.setEnabled(true);
	    _generate.setEnabled(false);
	    _results.setEnabled(true);
	    break;
	case Simulator.STOP:
	    _network.setSelected(false);
	    _new.setEnabled(true);
	    _open.setEnabled(true);
	    _save.setEnabled(true);
	    _arrow.setEnabled(true);
	    _erase.setEnabled(true);
	    _mobile.setEnabled(true);
	    _base.setEnabled(true);
	    _sink.setEnabled(true);
	    _network.setEnabled(true);
	    _rectangle.setEnabled(true);
	    _circle.setEnabled(true);
	    _play.setEnabled(true);
	    _pause.setEnabled(false);
	    _stop.setEnabled(false);
	    _reload.setEnabled(true);
	    _snapshot.setEnabled(false);
	    _faster.setEnabled(false);
	    _slower.setEnabled(false);
	    _generate.setEnabled(true);
	    _results.setEnabled(true);
	    break;
	default:	
	}
    }
}

